package bankrmi;

import java.rmi.*;
import java.rmi.server.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AccountImpl extends UnicastRemoteObject
        implements bankrmi.Account {

    private float _balance = 0;
    private String _name;
    private String _password;
    private static final String tableName = "client";
    private String datasource = "bankbdd";
    private String dbms = "mysql";
    private Statement sqlStatement;

    /** Construct a persistently named object. */
    public AccountImpl(String name, String password) throws RemoteException {
        super();
        _name = name;
        _password = password;
        createDatasource();
    }

    public AccountImpl(String name, String password, float balance) throws RemoteException {
        super();
        _name = name;
        _password = password;
        _balance = balance;
        createDatasource();
    }

    /** Construct a transient object. */
    public AccountImpl() throws RemoteException {
        super();
    }

    private void createDatasource() {
        try {
            Connection connection = getConnection();
            System.out.println("connected to the BDD");
            sqlStatement = connection.createStatement();
            boolean exist = false;

            DatabaseMetaData dbm = connection.getMetaData();
            for (ResultSet rs = dbm.getTables(null, null, "client", null); rs.next();) {
                exist = true;
                rs.close();
                System.out.println("the table already exists");
                break;
            }
            if (!exist) {
                System.out.println("create a new table named client");
                sqlStatement.executeUpdate("CREATE TABLE client (id int PRIMARY KEY, name VARCHAR(20), password VARCHAR(50), balance float)");
            }
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(BankImpl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException ex) {
            Logger.getLogger(BankImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private Connection getConnection() throws ClassNotFoundException, SQLException {
        if (dbms.equalsIgnoreCase("mysql")) {
            Class.forName("com.mysql.jdbc.Driver");
            return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/" + datasource, "root", "");
        } else {
            return null;
        }
    }

    public String getPassword() {
        return _password;
    }

    @Override
    public synchronized void deposit(float value)
            throws RemoteException, Rejected {
        try {
            if (value < 0) {
                throw new Rejected("Rejected: Account "
                        + _name
                        + ": Illegal value: "
                        + value);
            }
            _balance += value;
            sqlStatement.executeUpdate("UPDATE client SET balance="+_balance+" where name='"+_name+"'");
            System.out.println("Transaction: Account "
                    + _name + ": deposit: $"
                    + value + ", balance: $"
                    + _balance);
        } catch (SQLException ex) {
            System.out.println("imposible to make a deposit on the bdd");
        }
    }

    @Override
    public synchronized void withdraw(float value)
            throws RemoteException, Rejected {
        try {
            if (value < 0) {
                throw new Rejected("Rejected: Account "
                        + _name
                        + ": Illegal value: "
                        + value);
            }
            if ((_balance - value) < 0) {
                throw new Rejected("Rejected: Account "
                        + _name
                        + ": Negative balance "
                        + "on withdraw: "
                        + (_balance - value));
            }
            _balance -= value;
            
            sqlStatement.executeUpdate("UPDATE client SET balance="+_balance+" where name='"+_name+"'");
            System.out.println("Transaction: Account "
                    + _name + ": withdraw: $"
                    + value + ", balance: $"
                    + _balance);
        } catch (SQLException ex) {
            System.out.println("imposible to make a withdrawal on the bdd");
        }
    }

    @Override
    public synchronized float balance()
            throws RemoteException {
        try {
            ResultSet result = sqlStatement.executeQuery("SELECT balance FROM client WHERE name='"+_name+"'");
            
            if(result.next()){
                _balance = result.getFloat("balance");
            }
        } catch (SQLException ex) {
            System.out.println("unable to read balance account");
        }
        return _balance;
    }
}
